package com.qumitech.visualnovel.service.channel.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qumitech.visualnovel.component.util.MathUtils;
import com.qumitech.visualnovel.datasource.channel.ChannelDataMapper;
import com.qumitech.visualnovel.datasource.channel.LaunchChannelMapper;
import com.qumitech.visualnovel.datasource.console.ChannelDiamondDataDOMapper;
import com.qumitech.visualnovel.datasource.console.ChannelRechargeDataDOMapper;
import com.qumitech.visualnovel.datasource.console.ChannelJoyCoinsDataDOMapper;
import com.qumitech.visualnovel.datasource.console.AccountLoginStatisticsMapper;
import com.qumitech.visualnovel.model.dao.channel.ChannelData;
import com.qumitech.visualnovel.model.dao.console.ChannelDiamondDataDO;
import com.qumitech.visualnovel.model.dao.console.ChannelRechargeDataDO;
import com.qumitech.visualnovel.model.dao.console.ChannelJoyCoinsDataDO;
import com.qumitech.visualnovel.model.dao.channel.LaunchData;
import com.qumitech.visualnovel.model.dao.channel.LaunchChannelData;
import com.qumitech.visualnovel.model.dao.channel.LaunchExpense;
import com.qumitech.visualnovel.pubdef.dto.asa.asaDTO;
import com.qumitech.visualnovel.service.channel.ChannelDataService;
import com.google.common.base.Joiner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * Created by Edison.hu on 18/9/20.
 */
@Service
public class ChannelDataServiceImpl implements ChannelDataService {

    @Autowired
    ChannelDataMapper channelDataMapper;

    @Autowired
    ChannelDiamondDataDOMapper diamondDataDOMapper;

    @Autowired
    ChannelRechargeDataDOMapper rechargeDataDOMapper;

    @Autowired
    ChannelJoyCoinsDataDOMapper channelJoyCoinsDataDOMapper;

    @Autowired
    AccountLoginStatisticsMapper accountLoginStatisticsMapper;

    @Autowired
    LaunchChannelMapper launchChannelMapper;



    @Override
    public List<ChannelData> ChannelDataList(String startTime, String endTime, String channel, String appId, int offset,
                                             int pageSize,String orderType,String orderBy,Integer channelType){
        return channelDataMapper.getChannelDataList(startTime, endTime, channel, appId,
                offset, pageSize, orderType, orderBy,channelType);
    }

    @Override
    public List<HashMap<String,Object>> getChannelOptions(){
        return channelDataMapper.getChannelOptions();
    }

    @Override
    public int ChannelDataListCount(String startTime,String endTime,String channel,String appId,Integer channelType){
        return channelDataMapper.ChannelDataListCount( startTime, endTime, channel, appId, channelType);
    }

    @Override
    public JSONArray ChannelDataStatistic(String startTime, String endTime,
                                          String channel, String appId, Integer channelType) {
        HashMap channelDataTotal = channelDataMapper.getTotalValue(startTime, endTime, channel, appId, channelType);
        JSONObject data = new JSONObject();
        if (channel != null) {
            data.put("channel", channelDataTotal.get("channel"));
        }
        else{
            data.put("channel", "-");
        }
        if (startTime != null){
            data.put("time_str", startTime + "--" + endTime);
        }
        else{
            data.put("time_str", "-");
        }
        data.put("income", channelDataTotal.get("income"));
        data.put("register_count", channelDataTotal.get("register_count"));
        JSONArray dataArray = new JSONArray();
        dataArray.add(data);
        return dataArray;
    }

    @Override
    public List<ChannelDiamondDataDO> ChannelDiamondList(String startTime, String endTime, List<String> channelList,
                                                         int offset, int pageSize, String orderType, String orderBy) {
        return diamondDataDOMapper.getList(startTime, endTime, channelList, offset, pageSize, orderType, orderBy);
    }

    @Override
    public int ChannelDiamondCount(String startTime, String endTime, List<String> channelList) {
        return diamondDataDOMapper.getCount(startTime, endTime, channelList);
    }

    @Override
    public List<ChannelRechargeDataDO> ChannelRechargeList(String startTime, String endTime, List<String> channel,
                                                           int offset, int pageSize, String orderType, String orderBy) {
        return rechargeDataDOMapper.getList(startTime, endTime, channel, offset, pageSize, orderType, orderBy);
    }

    @Override
    public int ChannelRechargeCount(String startTime, String endTime, List<String> channel) {
        return rechargeDataDOMapper.getCount(startTime, endTime, channel);
    }

    @Override
    public int ChannelJoyCoinsCount(String startTime,String endTime,List<String> channelList) {
        return channelJoyCoinsDataDOMapper.getCount(startTime, endTime, channelList);
    }

    @Override
    public List<ChannelJoyCoinsDataDO> ChannelJoyCoinsList(String startTime,String endTime,List<String> channelList, int offset, int pageSize,String orderType,String orderBy){
        return channelJoyCoinsDataDOMapper.getList(startTime, endTime, channelList, offset, pageSize, orderType, orderBy);
    }

    public List<LaunchData> generateLaunchData(List<LaunchData> launchDataList) {
        for (LaunchData launchData : launchDataList) {
            if (launchData == null) {
                launchDataList.remove(launchData);
                break;
            }
            if (launchData.getChannel() != null && launchData.getChannel().equals("total")) {
                launchData.setChannel("合计");
            }
            Float expense = launchData.getExpense();
            Long downloadCount = launchData.getDownloadCount();
            if (expense != null && expense != 0) {
                if (launchData.getComputeCount() != null && launchData.getComputeCount() != 0) {
                    launchData.setRegisterCost(MathUtils.format2((double) (expense / launchData.getComputeCount())));
                }
                if (launchData.getActivatedCount() != null && launchData.getActivatedCount() != 0) {
                    launchData.setActivateCost(MathUtils.format2((double) (expense / launchData.getActivatedCount())));
                }
                if (launchData.getRecentRechargeHeadCount() != null && launchData.getRecentRechargeHeadCount() != 0) {
                    launchData.setRechargeCost(MathUtils.format2((double) (expense / launchData.getRecentRechargeHeadCount())));
                }
                if (launchData.getNewRechargePayCount() != null) {
                    launchData.setFirstDayROI(MathUtils.format2((double) (launchData.getNewRechargePayCount() / expense)));
                }
                if (launchData.getWeeklyRechargePayCount() != null) {
                    launchData.setWeeklyROI(MathUtils.format2((double) (launchData.getWeeklyRechargePayCount() / expense)));
                }
                if (launchData.getMonthlyRechargePayCount() != null) {
                    launchData.setMonthlyROI(MathUtils.format2((double) (launchData.getMonthlyRechargePayCount() / expense)));
                }
                if (launchData.getConsume() != null) {
                    launchData.setFirstDayProfit(MathUtils.format2((double) (launchData.getConsume() - expense)));
                    launchData.setFirstDayConsumeROI(MathUtils.format4((double) (launchData.getConsume() / expense)));
                }
                if (launchData.getSecondDayConsume() != null) {
                    launchData.setSecondDayProfit(MathUtils.format2((double) (launchData.getSecondDayConsume() - expense)));
                    launchData.setSecondDayConsumeROI(MathUtils.format4((double) (launchData.getSecondDayConsume() / expense)));
                }
                if (launchData.getThirdDayConsume() != null) {
                    launchData.setThirdDayProfit(MathUtils.format2((double) (launchData.getThirdDayConsume() - expense)));
                    launchData.setThirdDayConsumeROI(MathUtils.format4((double) (launchData.getThirdDayConsume() / expense)));
                }
                if (launchData.getFourthDayConsume() != null) {
                    launchData.setFourthDayProfit(MathUtils.format2((double) (launchData.getFourthDayConsume() - expense)));
                    launchData.setFourthDayConsumeROI(MathUtils.format4((double) (launchData.getFourthDayConsume() / expense)));
                }
                if (launchData.getFifthDayConsume() != null) {
                    launchData.setFifthDayProfit(MathUtils.format2((double) (launchData.getFifthDayConsume() - expense)));
                    launchData.setFifthDayConsumeROI(MathUtils.format4((double) (launchData.getFifthDayConsume() / expense)));
                }
                if (launchData.getSixthDayConsume() != null) {
                    launchData.setSixthDayProfit(MathUtils.format2((double) (launchData.getSixthDayConsume() - expense)));
                    launchData.setSixthDayConsumeROI(MathUtils.format4((double) (launchData.getSixthDayConsume() / expense)));
                }
                if (launchData.getWeeklyConsume() != null) {
                    launchData.setWeeklyProfit(MathUtils.format2((double) (launchData.getWeeklyConsume() - expense)));
                    launchData.setWeeklyConsumeROI(MathUtils.format4((double) (launchData.getWeeklyConsume() / expense)));
                }
                if (launchData.getMonthlyConsume() != null) {
                    launchData.setMonthlyProfit(MathUtils.format2((double) (launchData.getMonthlyConsume() - expense)));
                    launchData.setMonthlyConsumeROI(MathUtils.format4((double) (launchData.getMonthlyConsume() / expense)));
                }
            }
            if (downloadCount != null && downloadCount !=0) {
                if (launchData.getActivatedCount() != null && launchData.getActivatedCount() != 0) {
                    Double activateRate = launchData.getActivatedCount().doubleValue() / downloadCount.doubleValue();
                    launchData.setActivateRate(MathUtils.format4(activateRate));
                }
            }
        }
        return launchDataList;
    }

    @Override
    public JSONObject LaunchDataList(String startTime,String endTime,String channel,String appId,int offset,
                                           int pageSize,String orderType,String orderBy,Integer channelType, Integer filter) {
        if (channel != null && channel.contains("total")) {
            channel = "total";
        }
        List<LaunchData> launchDataList;
        List<LaunchData> launchDataListSum;
        String tableName;
        if (filter == 0) {
            tableName = "statistics_launch_data_unfiltered";
        } else {
            tableName = "statistics_launch_data";
        }

        if (channel == null || !channel.contains(",")) {
            launchDataList = channelDataMapper.getLaunchDataList(startTime, endTime, channel, appId,
                    offset, pageSize, orderType, orderBy,channelType, tableName);
            launchDataListSum = channelDataMapper.getLaunchDataListSum(startTime, endTime, channel, appId, channelType, tableName);
        } else {
            String channelReg = ":" + Joiner.on("$|:").join(channel.split(",")) + "$";
            launchDataList = channelDataMapper.getLaunchDataListTotal(startTime, endTime, channelReg, appId, offset,
                    pageSize, orderType, orderBy, channelType, tableName, 0);
            launchDataListSum = channelDataMapper.getLaunchDataListTotal(startTime, endTime, channelReg, appId, offset,
                    pageSize, orderType, orderBy, channelType, tableName, 1);
        }

        List<LaunchData> newLaunchDataList = generateLaunchData(launchDataList);
        List<LaunchData> newLaunchDataListSum = generateLaunchData(launchDataListSum);

        JSONObject result = new JSONObject();
        result.put("items", newLaunchDataList);
        result.put("sum", newLaunchDataListSum);

        return result;
    }

    @Override
    public int LaunchDataListCount(String startTime,String endTime,String channel,String appId, Integer channelType, Integer filter) {
        String tableName;
        if (filter == 0) {
            tableName = "statistics_launch_data_unfiltered";
        } else {
            tableName = "statistics_launch_data";
        }
        if (channel != null && channel.contains(",")) {
            channel = "total";
        }
        return channelDataMapper.LaunchDataListCount(startTime, endTime, channel, appId, channelType, tableName);
    }

    @Override
    public List<LaunchChannelData> LaunchChannelList(String startTime, String endTime, String channel, Integer status, int offset, int pageSize, String orderType, String orderBy) {
        return launchChannelMapper.getLaunchChannelData(startTime, endTime, channel, status, offset, pageSize, orderType, orderBy);
    }

    @Override
    public int LaunchChannelListCount(String startTime, String endTime, String channel, Integer status) {
        return launchChannelMapper.getLaunchChannelDataCount(startTime, endTime, channel, status);
    }

    @Override
    public List<String> listConsumeROIReference() {
        return launchChannelMapper.getConsumeROIReference();
    }

    @Override
    public int addLaunchChannel(String channel) {
        List<LaunchChannelData> launchChannelData = launchChannelMapper.getLaunchChannelData(null,null, channel,1,0,1, "asc", "target_date");
        if (launchChannelData.size() != 0) {
            return 0;
        }
        Date date = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String targetDate = formatter.format(date);
        launchChannelMapper.insert(channel, targetDate);
        return 1;
    }

    @Override
    public void updateLaunchChannelStatus(String channel) {
        launchChannelMapper.updateLaunchChannelStatus(channel);
    }

    @Override
    public List<LaunchExpense> LaunchExpenseList(String startTime, String endTime, String channel, int offset, int limit, String orderBy, String orderType) {
        return channelDataMapper.getLaunchExpenseList(startTime, endTime, channel, offset, limit, orderBy, orderType);
    }

    @Override
    public int LaunchExpenseListCount(String startTime, String endTime, String channel) {
        return channelDataMapper.getLaunchExpenseListCount(startTime, endTime, channel);
    }

    @Override
    public void updateLaunchExpense(List<LaunchExpense> launchExpenses) {
        for (LaunchExpense launchExpense: launchExpenses) {
            String targetDate = launchExpense.getTargetDate();
            String channel = launchExpense.getChannel();
            Float expense = launchExpense.getExpense();
            Long downloadCount = launchExpense.getDownloadCount();
            if (expense == null && downloadCount == null || targetDate == null || channel == null) {
                break;
            }
            channelDataMapper.updateLaunchExpense(targetDate, channel, expense, downloadCount, "statistics_launch_data");
            channelDataMapper.updateLaunchExpense(targetDate, channel, expense, downloadCount, "statistics_launch_data_unfiltered");
            channelDataMapper.updateLaunchTotalExpense(targetDate, "statistics_launch_data");
            channelDataMapper.updateLaunchTotalExpense(targetDate, "statistics_launch_data_unfiltered");
        }
    }

    @Override
    public List<asaDTO> asaDataList(String keywordId, String keywordName, String startTime, String endTime, Integer filter,
                                    String orderType, String orderBy, int offset, int limit) {
        return diamondDataDOMapper.asaDataList(keywordId, keywordName, startTime, endTime, filter, orderType, orderBy, offset, limit);

    }

    @Override
    public int asaDataListCount(String keywordId, String keywordName, String startTime,String endTime, Integer filter) {
        return diamondDataDOMapper.asaDataCount(keywordId, keywordName, startTime, endTime, filter);
    }

    @Override
    public List<asaDTO> asaDataListListSum(String keywordId, String keywordName, String startTime,String endTime, Integer filter) {
        return diamondDataDOMapper.asaDataListSum(keywordId, keywordName, startTime, endTime, filter);
    }

}
